package com.manage.common.filter;

import com.manage.common.config.AuthConfig;
import com.manage.common.utils.JwtUtil;
import io.jsonwebtoken.ExpiredJwtException;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.Cookie;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import java.io.IOException;
import java.util.ArrayList;

/**
 * 授权过滤器，验证Token合法性
 */
public class JWTAuthorizationFilter extends BasicAuthenticationFilter {

    // 建议注入JwtUtil，而非每次new（需在Security配置中注入）
    private final JwtUtil jwtUtil;

    // 构造方法注入JwtUtil（修改此处，避免硬编码new）
    public JWTAuthorizationFilter(AuthenticationManager authenticationManager, JwtUtil jwtUtil) {
        super(authenticationManager);
        this.jwtUtil = jwtUtil;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request,
                                    HttpServletResponse response,
                                    FilterChain chain) throws IOException, ServletException {
        // 1. 放行无需认证的路径
        String requestURI = request.getRequestURI();
        if (isPermittedPath(requestURI)) {
            chain.doFilter(request, response);
            return;
        }

        // 2. 获取 Token
        String tokenHeader = getTokenFromCookie(request);
        if (tokenHeader == null) {
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"code\":401,\"message\":\"未提供 Token\"}");
            return;
        }

        try {
            // 3. 验证 Token 并设置认证信息
            UsernamePasswordAuthenticationToken authentication = getAuthentication(tokenHeader);
            if (authentication != null) {
                SecurityContextHolder.getContext().setAuthentication(authentication);
                chain.doFilter(request, response);
            } else {
                response.setContentType("application/json;charset=UTF-8");
                response.getWriter().write("{\"code\":401,\"message\":\"无效的 Token\"}");
            }
        } catch (ExpiredJwtException e) {
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"code\":401,\"message\":\"Token 已过期\"}");
        } catch (Exception e) {
            response.setContentType("application/json;charset=UTF-8");
            response.getWriter().write("{\"code\":500,\"message\":\"服务器错误\"}");
        }
    }

    // 从 Token 中解析认证信息
    private UsernamePasswordAuthenticationToken getAuthentication(String tokenHeader) {
        try {
            // 1. 去掉前缀（如果有）
            String token = tokenHeader;
            if (tokenHeader.startsWith(AuthConfig.TOKEN_PREFIX)) {
                token = tokenHeader.replace(AuthConfig.TOKEN_PREFIX, "");
            }

            // 2. 解析 Token
            String username = jwtUtil.getUsernameFromToken(token);
            if (username != null && !jwtUtil.isTokenExpired(token)) { // 注意：!isTokenExpired
                return new UsernamePasswordAuthenticationToken(username, null, new ArrayList<>());
            }
        } catch (Exception e) {
            System.out.println("Token 解析失败: " + e.getMessage());
        }
        return null;
    }

    /**
     * 检查是否是放行的路径（如 Swagger/Knife4j）
     */
    private boolean isPermittedPath(String requestURI) {
        String[] permittedPaths = {
                "/doc.html",
                "/webjars/",
                "/v3/api-docs/",
                "/swagger-resources/",
                "/swagger-ui/",
                "/favicon.ico",
                "/auth/login",
                "/auth/register"
        };
        for (String path : permittedPaths) {
            if (requestURI.startsWith(path)) {
                return true;
            }
        }
        return false;
    }

    // 从请求的 Cookie 中提取名为 "auth_token" 的 token
    private String getTokenFromCookie(HttpServletRequest request) {
        Cookie[] cookies = request.getCookies();
        if (cookies != null) {
            for (Cookie cookie : cookies) {
                if ("auth_token".equals(cookie.getName())) { // 与登录时设置的 Cookie 名称一致
                    return cookie.getValue();
                }
            }
        }
        return null; // 未找到 token Cookie
    }

}
